#pragma once
#include <iostream>
#include <pthread.h>
#include <string>
#include <vector>
#include <assert.h>
#include <sys/types.h>
#include <unistd.h>
#include <functional>
// 自己封装一个线程对象，调用时创建当前线程的名称，然后在启动对应的start函数时调用传入的start_routine
// 由于this指针的存在，编写对应的函数时需要使用静态函数

namespace ThreadSpace
{
	class Thread
	{

		// 具体的实现逻辑像是暗度陈仓，既然没办法直接调用对应的成员变量，使用static可以消除this指针的影响
		// 但是还需要执行传入的方法，这个时候我们可以把当前对象的this指针当成参数传入，在调用对应的执行方法的时候
		// 相当于直接拿到了自己， 那么就可以自己调用自身已经传入过的方法。
	
	private:
		static void* start_routine(void* args)
		{
			Thread* _this = static_cast<Thread*>(args);
			return _this->_mission(_this->_args);
		}

	public:
		using fun_t = std::function<void *(void *)>;
		// using  fun_t = void* (*)(void*);直接用函数指针就不用关系包装器的问题了，但其实主要的问题还是在于这样的Thread类
		// 没办法调用自身的成员函数，所以还是需要用别的方法试试

		// 创建一个线程，需要接收传入的对应执行方法函数,但我们不在构造函数期间直接创建，而是构造对应的线程名称
		Thread()
		{
			char name[1024];
			snprintf(name, sizeof(name), "%d号线程", _num++);
			_name = name;
		}

		// start函数，创建对应的线程，传入对应的执行方法以及传入参数
		void start(fun_t mission, void *args = nullptr)
		{
			_mission = mission;
			_args = args;
			int n = pthread_create(&_id, nullptr, start_routine,this); // TODO
			assert( n == 0);
		}
		void join()
        {
            int n = pthread_join(_id, nullptr);
            assert(n == 0);
        }

		std::string getname()
		{
			return _name;
		}
		// 析构阶段
		~Thread()
		{}

	private:
		pthread_t _id;
		fun_t _mission;
		void *_args;
		static int _num;
		std::string _name;
	};

	 int Thread:: _num = 1;

}
